package api

import (
	_ "apifast/api/controller"
	_ "apifast/api/system"
	"apifast/configs"
	"apifast/middleware"
	"apifast/pkg/router"
	"apifast/util"
	"apifast/views"
	"context"
	"fmt"
	"log"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
)

type Options struct {
	Timeout int64
	Port    uint16
	Root    string
	Public  string
}

// initRouter 创建gin对象
func initRouter(o *Options) *gin.Engine {
	// gin.SetMode(gin.ReleaseMode)
	r := gin.Default()
	// r.Use(middleware.LoadTLS()) // https
	r.Use(middleware.Cors()) // 跨域
	views.Static(r, o.Root)
	v1 := r.Group("/api/v1")
	router.Init(v1)
	v1.StaticFS("/public", http.Dir(util.Public.Abs(o.Public)))
	return r
}

var s *http.Server

// New
func Run() error {
	var opts Options
	if err := configs.GViper.UnmarshalKey("serve", &opts); err != nil {
		return err
	}
	r := initRouter(&opts)
	address := fmt.Sprintf(":%d", opts.Port)
	s := &http.Server{
		Addr:           address,
		Handler:        r,
		ReadTimeout:    time.Duration(opts.Timeout) * time.Second,
		WriteTimeout:   time.Duration(opts.Timeout) * time.Second,
		MaxHeaderBytes: 1 << 20,
	}
	log.Printf("%s serve start at %s", configs.AppName, address)
	go s.ListenAndServe()
	return nil
}

func Shutdown() error {
	if s != nil {
		ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
		defer cancel()
		s.Shutdown(ctx)
		// catching ctx.Done(). timeout of 5 seconds.
		<-ctx.Done()
	}
	return nil
}
